/**
 * Created by jinxs on 14-8-13.
 */
(function ($) {
    /**
     * 缓存名称
     * @type {string}
     * @private
     */
    var _cacheName = 'uiCombo';
    /**
     * @class 下拉框－基类
     * @requires {@link uiPanel}
     * @constructor uiCombo
     * @summary 构造函数
     * @param [options] {Object|String} 组件配置参数|要调用的组件方法名
     * @param [param] {Object} 表示要调用的组件方法的参数
     * @example
     * // 构件组件
     * $('#selectAge').uiCombo({direction: 'left'});
     * // 调用组件方法options
     * $('#selectAge').uiCombo("options");
     */
    $.fn.uiCombo = function (options, param) {
        if (typeof options == "string") {
            return $.fn.uiCombo.methods[options](this, param);
        }
        return this.each(function(){
            var me = $(this);
            options = options || {};

            var state = me.data(_cacheName);
            if (state) {
                $.extend(state.options, options);
            } else {
                me.data(_cacheName, {
                    options: $.extend({}, $.fn.uiCombo.defaults, me.parseUIConfig(), options),
                    previousValue: null
                });
                _init(me);
                me.removeAttr("disabled");
            }
            _create(me);
            _bindEvent(me);
            _addValidate(me);
            _resizeWidth(me);
            _setInitValues(me);
        });
    };

    /**
     * 方法
     * @lends uiCombo.prototype
     */
    $.fn.uiCombo.methods = {
        /**
         * @summary 获得组件的配置对象
         * @name uiCombo#options
         * @function
         * @returns {Object} 组件的配置对象
         */
        options: function (target) {
            return $.data(target[0], _cacheName).options;
        },
        /**
         * @summary 获得组件的面板对象
         * @name uiCombo#panel
         * @function
         * @returns {jQuery} 组件的面板对象的内容
         */
        panel: function (target) {
            var targetID = target.getElemID();
            var panel = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboPanel);
            return panel.uiPanel('content');
        },
        panelBar: function (target) {
            var targetID = target.getElemID();
            var panel = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboPanel);
            return panel.uiPanel('buttonbar');
        },
        /**
         * @summary 获得组件的文本框
         * @name uiCombo#textbox
         * @function
         * @returns {jQuery} 组件的文本框
         */
        combo: function (target) {
            var targetID = target.getElemID();
            return $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
        },
        /**
         * @summary 获得组件的文本框
         * @name uiCombo#textbox
         * @function
         * @returns {jQuery} 组件的文本框
         */
        textbox: function (target) {
            var targetID = target.getElemID();
            return $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        },
        /**
         * @summary 移除并返回组件
         * @name uiCombo#destroy
         * @function
         * @returns {jQuery} 组件对象
         */
        destroy: function (target) {
            _destory(target);
            return target;
        },
        /**
         * @summary 设置控件的宽度
         * @name uiCombo#resize
         * @function
         * @param width {Number} 宽度大小
         * @returns {jQuery} 方法调用者
         */
        resize: function (target, width) {
            _resizeWidth(target, width);
            return target;
        },
        /**
         * @summary 显示组件的面板
         * @name uiCombo#showPanel
         * @function
         * @returns {jQuery} 组件对象
         */
        showPanel: function (target) {
            _showPanel(target);
            return target;
        },
        /**
         * @summary 隐藏组件的面板
         * @name uiCombo#hidePanel
         * @function
         * @returns {jQuery} 组件对象
         */
        hidePanel: function (target) {
            _closeThisPal(target);
            return target;
        },
        /**
         * @summary 禁用组件
         * @name uiCombo#disable
         * @function
         * @returns {jQuery} 组件对象
         */
        disable: function (target) {
            _setDisabled(target, true);
            _bindEvent(target);
            return target;
        },
        /**
         * @summary 启用组件
         * @name uiCombo#enable
         * @function
         * @returns {jQuery} 组件对象
         */
        enable: function (target) {
            _setDisabled(target, false);
            _bindEvent(target);
            return target;
        },
        /**
         * @summary 设置组件是否为只读
         * @name uiCombo#setReadonly
         * @function
         * @param readonly {Boolean} 是否为只读
         * @returns {jQuery} 组件对象
         */
        setReadonly: function (target, readonly) {
            _setReadonly(target, readonly);
            _bindEvent(target);
            return target;
        },
        /**
         * @summary 验证组件值的正确性
         * @name uiCombo#isValid
         * @function
         * @returns {Boolean} 组件值是否正确
         */
        isValid: function (target) {
            var targetID = target.getElemID();
            var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
            var combo = $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
            comboText.uiValidate('options').nullValue = target.uiCombo('options').nullValue;
            var valid = comboText.uiValidate("isValid");
            if (!valid) {
                combo.addClass('ui_combo-invalid');
            } else {
                combo.removeClass('ui_combo-invalid');
            }
            return valid;
        },
        enableValidation: function (target) {
            var targetID = target.getElemID();
            var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
            comboText.uiValidate("enableValidation");
            return target;
        },
        disableValidation: function (target) {
            var targetID = target.getElemID();
            var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
            var combo = $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
            comboText.uiValidate("disableValidation");
            combo.removeClass('ui_combo-invalid');
            return target;
        },
        /**
         * @summary 清除组件的已选值
         * @name uiCombo#clear
         * @function
         * @returns {jQuery} 组件对象
         */
        clear: function (target) {
            _clear(target);
            return target;
        },
        /**
         * @summary 重置组件的值
         * @name uiCombo#reset
         * @function
         * @returns {jQuery} 组件对象
         */
        reset: function (target) {
            var options = $.data(target[0], _cacheName).options;
            if (options.multiple) {
                target.uiCombo("setValues", options.originalValue);
            } else {
                target.uiCombo("setValue", options.originalValue);
            }
            return target;
        },
        /**
         * @summary 获取组件的显示文本
         * @name uiCombo#getText
         * @function
         * @returns {String} 组件的显示文本
         */
        getText: function (target) {
            return _getText(target);
        },
        /**
         * @summary 设置组件的显示文本
         * @name uiCombo#setText
         * @function
         * @param text {String} 组件的显示文本
         * @returns {jQuery} 组件对象
         */
        setText: function (target, text) {
            _setText(target, text);
            return target;
        },
        /**
         * @summary 获取组件的值
         * @name uiCombo#getValues
         * @function
         * @returns {Array<String>} 组件的值列表
         */
        getValues: function (target) {
            return _getValues(target);
        },
        /**
         * @summary 设置组件的值
         * @name uiCombo#setValues
         * @function
         * @param values {Array<String>} 组件的值列表
         * @returns {jQuery} 组件对象
         */
        setValues: function (target, values) {
            _setValues(target, values);
            return target;
        },
        /**
         * @summary 获取组件的第一个选中值
         * @name uiCombo#getValue
         * @function
         * @returns {String} 组件的值
         */
        getValue: function (target) {
            return _getValue(target);
        },
        /**
         * @summary 设置组件的值
         * @name uiCombo#setValue
         * @function
         * @param value {String} 组件的值
         * @returns {jQuery} 组件对象
         */
        setValue: function (target, value) {
            _setValue(target, value);
            return target;
        }
    };

    $.fn.uiCombo.defaults = $.extend({}, $.fn.uiValidate.defaults,
        /**
         * 默认配置
         * @lends uiCombo.prototype
         */
        {
            /**
             * @type Boolean
             * @default true
             * @summary 是否将下列面板渲染至body中
             */
            renderInBody: true,
            showPanelBar: false,
            /**
             * @type Number
             * @default 22
             * @summary 组件高度
             */
            height: 25,
            /**
             * @type Number
             * @default null
             * @summary 组件下拉面板宽度
             */
            panelWidth: null,
            /**
             * @type Array<Number>
             * @default [0,33]
             * @summary 提示信息相对于组件的位置
             */
            tipOffset: [20, 0],
            /**
             * @type String
             * @default right
             * @summary 提示消息的位置
             */
            tipPosition: 'right',
            /**
             * @type Number
             * @default 自动
             * @summary 组件下拉面板高度
             */
            panelHeight: 0,
            /**
             * 值可为left, right, center
             * @type String
             * @default "left"
             * @summary 组件下拉面板对齐方式
             */
            panelAlign: "left",
            /**
             * @type Boolean
             * @default false
             * @summary 指示组件是否可多选
             */
            multiple: false,
            /**
             * TODO: summary
             * @type Boolean
             * @default false
             * @summary X
             */
            selectOnNavigation: true,
            /**
             * @type String
             * @default ","
             * @summary 组件多个值的分隔符
             */
            separator: ",",
            /**
             * @type Boolean
             * @default false
             * @summary 指示组件是否可编辑
             */
            editable: false,
            /**
             * @type Boolean
             * @default false
             * @summary 指示组件是否可输入查询
             */
            searchable: false,
            /**
             * @type Boolean
             * @default false
             * @summary 指示组件是否禁用
             */
            disabled: false,
            /**
             * @type Boolean
             * @default false
             * @summary 指示组件是否为只读
             */
            readonly: false,
            /**
             * @type Boolean
             * @default true
             * @summary 指示组件是否显示下拉图标
             */
            hasDownArrow: true,
            /**
             * @type String
             * @default ""
             * @summary 组件初始值
             */
            value: "",
            /**
             * @type Number
             * @default 200
             * @summary 组件输入框在编辑后执行查询前的延迟毫秒数
             */
            delay: 200,
            /**
             * TODO: summary
             * @type Number
             * @default 19
             * @summary X
             */
            deltaX: 19,
            /**
             * 每个事件方法的this指向组件jQuery对象，事件可包含：<br/><br/>
             * <TABLE cellSpacing="1" width="100%" class="params">
             * <TR>
             * <TH width="12%">事件</TH>
             * <TH width="88%">说明</TH></TR>
             * <TR><TD align=center>up</TD><TD>键盘上方向键按下时触发，方法包含一个参数e(事件对象)</TD></TR>
             * <TR><TD align=center>down</TD><TD>键盘下方向键按下时触发，方法包含一个参数e(事件对象)</TD></TR>
             * <TR><TD align=center>left</TD><TD>键盘左方向键按下时触发，方法包含一个参数e(事件对象)</TD></TR>
             * <TR><TD align=center>right</TD><TD>键盘右方向键按下时触发，方法包含一个参数e(事件对象)</TD></TR>
             * <TR><TD align=center>enter</TD><TD>键盘回车键按下时触发，方法包含一个参数e(事件对象)</TD></TR>
             * <TR><TD align=center>query</TD><TD>执行查询时时触发，方法包含两个参数val, e(组件输入框的值，事件对象)</TD></TR>
             * </TABLE>
             * @summary 在组件输入框有键盘事件时触发的一系列方法。
             * @name uiCombo#keyHandler
             * @default {}
             */
            keyHandler: {
                up: function (e) {
                },
                down: function (e) {
                },
                left: function (e) {
                },
                right: function (e) {
                },
                enter: function (e) {
                },
                query: function (q, e) {
                    return true;
                }
            },
            /**
             * @summary 在组件面板显示时触发的方法。
             * @event
             * @name uiCombo#onShowPanel
             * @this 组件jQuery对象
             * @default emptyFn
             */
            onShowPanel: function () {
            },
            /**
             * @summary 在组件面板隐藏时触发的方法。
             * @event
             * @name uiCombo#onHidePanel
             * @this 组件jQuery对象
             * @default emptyFn
             */
            onHidePanel: function () {
            },
            /**
             * @summary 在组件值改变时触发的方法。
             * @event
             * @name uiCombo#onChange
             * @param newValue {String} 组件新的值
             * @param oldValue {String} 组件旧的值
             * @this 组件jQuery对象
             * @default emptyFn
             */
            onChange: function (newValue, oldValue) {
            },
            addButton: null
        });
    var _init = function (target) {
        var options = $.data(target[0], _cacheName).options;
        if (isNaN(options.width)) {
            options.width = target.outerWidth();
        }
        if (_IEunder6) {
            setTimeout(function () {
                target.addClass("ui_comboOrigin");
            }, 100);
        } else {
            target.addClass("ui_comboOrigin");
        }
        target.setElemID();
        var targetID = target.getElemID();
        var reg = new RegExp('({comboID})', 'g');
        var combo = $($.uiTemplate.uiCombo.html.replace(reg, targetID)).insertAfter(target);
        combo.addClass('ui-default');
        var panel = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboPanel);
        if (panel && panel.length > 0) {

        } else {
            panel = $($.uiTemplate.uiCombo.panelHtml.replace(reg, targetID));
            options.renderInBody ? panel.appendTo('body') : panel.appendTo(target.parent());
            var buttons = [];
            var showButton = false;
            if (options.addButton) {
                buttons = [options.addButton];
                showButton = true;
            }
            panel.uiPanel({
                width: (options.panelWidth ? options.panelWidth : options.width),
                height: options.panelHeight,
                zIndex: 10001,
                showHeader: false,
                showBtnBar: showButton || options.showPanelBar,
                buttons: buttons,
                closed: true,
                onBeforeClose: function () {
                    _closePanel(target);
                }, onClose: function () {
                    var state = $.data(target[0], _cacheName);
                    if (state) {
                        state.options.onHidePanel.call(target);
                    }
                }
            });
        }
        var targetName = $(target).attr("name");
        var comboValue = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboValue);
        if (targetName) {
            comboValue.attr("name", targetName);
            target.removeAttr("name").attr("comboName", targetName);
        }
    };
    var _create = function (target) {
        var targetID = target.getElemID();
        var options = $.data(target[0], _cacheName).options;
        var arrow = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboArrow);
        if (options.hasDownArrow) {
            arrow.show();
        } else {
            arrow.hide();
        }
        _setDisabled(target, options.disabled);
        _setReadonly(target, options.readonly);
    };
    var _setDisabled = function (target, disabled) {
        var targetID = target.getElemID();
        var options = $.data(target[0], _cacheName).options;
        var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        var comboValue = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboValue);
        if (disabled) {
            options.disabled = true;
            target.attr("disabled", true);
            comboValue.attr("disabled", true);
            comboText.attr("disabled", true);
        } else {
            options.disabled = false;
            target.removeAttr("disabled");
            comboValue.removeAttr("disabled");
            comboText.removeAttr("disabled");
        }
    };

    var _setReadonly = function (target, readonly) {
        var targetID = target.getElemID();
        var options = $.data(target[0], _cacheName).options;
        options.readonly = readonly == undefined ? false : readonly;
        var combo = $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
        var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        var comboArrow = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboArrow);
        if (options.readonly) {
            combo.addClass('ui_validate_disabled');
            comboText.attr("readonly", options.readonly).css("cursor", "");
            comboArrow.css('display', 'none');
            var starId=target.attr('id')+'-star';
            $('#'+starId).remove();
        } else {
            combo.removeClass('ui_validate_disabled');
            comboText.attr("readonly", options.readonly).css("cursor", "pointer");
            comboArrow.css('display', 'inline-block');
        }
    };
    var _resizeWidth = function (target, width) {
        var targetID = target.getElemID();
        var options = $.data(target[0], _cacheName).options;
        var combo = $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
        if (width) {
            options.width = width;
        }
        var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        var comboArrow = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboArrow);
        var arrowWidth = options.hasDownArrow ? comboArrow.outerWidth() : 0;
        if(_IEunder7) {
            combo.width(options.width).height(options.height);
        }else{
            combo.width(options.width+2).height(options.height);
        }
        comboText.css({
            height: combo.height() + "px",
            lineHeight: combo.height() + "px",
            width: options.width - arrowWidth
        });
        comboArrow.outerHeight(combo.height());
    };

    var _destory = function (target) {
        var options = $.data(target[0], _cacheName).options;
        var targetID = target.getElemID();
        var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        var combo = $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
        var panel = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboPanel);
        comboText.uiValidate("destroy");
        panel.uiPanel("destroy");
        combo.remove();
        target.remove();
    };

    var _closePanel = function (target) {
        target.find(".ui_comboOrigin").each(function () {
            var p = $.getByParentID(this.id, $.uiTemplate.uiCombo.comboPanel);
            if (p.is(":visible")) {
                p.uiPanel("close");
            }
        });
    };
    var _bindEvent = function (target) {
        var targetID = target.getElemID();
        var state = $.data(target[0], _cacheName);
        var options = state.options;
        var combo = $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
        var panel = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboPanel);
        var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        var comboArrow = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboArrow);
        $(document).unbind(".uiCombo").bind("mousedown.uiCombo", function (e) {
            var p = $(e.target).closest("span.ui_combo,div.ui_combo-panel");
            if (p.length) {
                _closePanel(target);
                return;
            }
            $("body>div.ui_combo-panel:visible").each(function () {
                $(this).uiPanel("close");
            });
        });
        comboText.unbind(".uiCombo");
        comboArrow.unbind(".uiCombo");
        if (!options.disabled && !options.readonly) {
            combo.bind('mouseover.uiCombo', function (e) {
                combo.addClass('ui-hover');
            })
                .bind('mouseleave.uiCombo', function (e) {
                    combo.removeClass('ui-hover');
                })
            comboText.bind("click.uiCombo", function (e) {
                if (!options.editable) {
                    _show.call(this);
                } else {
                    var p = $(this).closest("div.ui_combo-panel");
                    $("div.ui_combo-panel").not(panel).not(p).each(function () {
                        $(this).uiPanel("close");
                    })
                }
            })
                .bind("keydown.uiCombo paste.uiCombo drop.uiCombo", function (e) {
                    switch (e.which) {
                        case $.keyCode.UP:
                            options.keyHandler.up.call(target, e);
                            break;
                        case $.keyCode.DOWN:
                            options.keyHandler.down.call(target, e);
                            break;
                        case $.keyCode.LEFT:
                            options.keyHandler.left.call(target, e);
                            break;
                        case $.keyCode.RIGHT:
                            options.keyHandler.right.call(target, e);
                            break;
                        case $.keyCode.ENTER:
                            e.preventDefault();
                            options.keyHandler.enter.call(target, e);
                            return false;
                        case $.keyCode.TAB:
                        case $.keyCode.ESCAPE:
                            _closeThisPal(target);
                            break;
                        default:
                            if (options.editable || options.searchable) {
                                if (state.timer) {
                                    clearTimeout(state.timer);
                                }
                                state.timer = setTimeout(function () {
                                    var txt = comboText.val();
                                    if (state.previousValue != txt) {
                                        state.previousValue = txt;
                                        target.uiCombo("showPanel");
                                        options.keyHandler.query.call(target, comboText.val(), e);
                                        target.uiCombo("isValid");
                                    }
                                }, options.delay);
                            }
                    }
                });
            if (webUI_browser().gecko) {
                comboText.bind('input', function (e) {
                    comboText.keydown();
                });
            }
            comboArrow.bind("click.uiCombo", function () {
                _show.call(this);
            })
                .bind("mouseenter.uiCombo", function () {
                    $(this).addClass("ui_combo-arrow-hover");
                })
                .bind("mouseleave.combo", function () {
                    $(this).removeClass("ui_combo-arrow-hover");
                });
        }
        function _show() {
            if (panel.attr('closed') == 'false') {
                _closeThisPal(target);
            } else {
                var p = $(this).closest("div.ui_combo-panel");
                var panels = $("div.ui_combo-panel").not(panel).not(p);
                if (panels.length > 0) {
                    panels.each(function () {
                        $(this).uiPanel("close");
                    })
                }
                $(target).uiCombo("showPanel");
            }
        }

        if (!options.editable && !options.searchable) {
            comboText.attr('readonly', true);
        }
    };

    function _showPanel(target) {
        var targetID = target.getElemID();
        var options = $.data(target[0], _cacheName).options;
        var combo = $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
        var panel = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboPanel);
        panel.css({left: _calcLeft(), top: calcTop()});
        if (panel.uiPanel("options").closed) {
            panel.uiPanel("open");
            options.onShowPanel.call(target);
        }
        (function () {
            if (panel.attr('closed') == 'false') {
                panel.css({left: _calcLeft(), top: calcTop()});
                setTimeout(arguments.callee, 200);
            }
        })();
        function _calcLeft() {
            if (options.renderInBody) {
                //如果添加到body的算法
                var left = combo.offset().left;
                if (options.panelAlign == "right") {
                    left += combo.outerWidth() - panel.outerWidth();
                }
                if (left + panel.outerWidth() > $(window).outerWidth() + $(document).scrollLeft()) {
                    left = $(window).outerWidth() + $(document).scrollLeft() - panel.outerWidth();
                }
                if (left < 0) {
                    left = 0;
                }
            } else {
                //如果添加到target的父容器中
                var left = combo.position().left + combo.closest('div').scrollLeft();
            }
            return left;
        }

        function calcTop() {
            if (options.renderInBody) {
                //如果添加到body的算法
                var comboTop = combo.offset().top;
                var top = combo.offset().top + combo.outerHeight();
                if (top + panel.outerHeight() > $(window).outerHeight() + $(document).scrollTop()) {
                    top = comboTop - panel.outerHeight();
                }
                if (top < $(document).scrollTop()) {
                    top = comboTop + combo.outerHeight();
                }
            } else {
                //如果添加到target的父容器中
                var top = combo.position().top + combo.outerHeight() + combo.closest('div').scrollTop();
            }
            return top;
        }
    }

    var _closeThisPal = function (target) {
        var targetID = target.getElemID();
        var panel = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboPanel);
        panel.uiPanel("close");
    };

    var _addValidate = function (target) {
        var targetID = target.getElemID();
        var options = $.data(target[0], _cacheName).options;
        var combo = $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
        var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        comboText.uiValidate(options);
        if (comboText.hasClass('ui_validate-invalid')) {
            combo.addClass('ui_combo-invalid');
        }
    };

    var _clear = function (target) {
        var targetID = target.getElemID();
        var options = $.data(target[0], _cacheName).options;
        var combo = $.getByParentID(targetID, $.uiTemplate.uiCombo.combo);
        var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        var comboValue = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboValue);
        comboValue.val("");
        comboText.val("");
    };

    var _getText = function (target) {
        var targetID = target.getElemID();
        var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        return comboText.val();
    };

    var _setText = function (target, text) {
        var targetID = target.getElemID();
        var state = $.data(target[0], _cacheName);
        var comboText = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboText);
        if (comboText.val() != text) {
            comboText.val(text);
            target.uiCombo("isValid");
            state.previousValue = text;
        }
    };
    var _getValues = function (target) {
        var options = $.data(target[0], _cacheName).options;
        var values = [];
        var targetID = target.getElemID();
        var comboValues = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboValue).val();
        var valueList = comboValues.split(options.separator);
        for (var i = 0; i < valueList.length; i++) {
            var val = valueList[i];
            if ($.trim(val) != '') {
                values.push(valueList[i]);
            }
        }
        return values;
    };

    var _setValues = function (target, values) {
        var state = $.data(target[0], _cacheName);
        var options = state.options;
        var targetID = target.getElemID();
        var oldValues = _getValues(target);
        var comboName = target.attr("comboName");
        var comboValue = $.getByParentID(targetID, $.uiTemplate.uiCombo.comboValue);
        if (comboName) {
            comboValue.attr("name", comboName);
        }
        var selValues = '';
        for (var i = 0; i < values.length; i++) {
            var val = values[i];
            if ($.trim(val) != '') {
                selValues += values[i] + options.separator;
            }
        }
        comboValue.val(selValues.substr(0, selValues.length - 1));
        var tmp = [];
        for (var i = 0; i < oldValues.length; i++) {
            tmp[i] = oldValues[i];
        }
        var newValues = [];
        for (var i = 0; i < values.length; i++) {
            for (var j = 0; j < tmp.length; j++) {
                if (values[i] == tmp[j]) {
                    newValues.push(values[i]);
                    tmp.splice(j, 1);
                    break;
                }
            }
        }
        if (newValues.length != values.length || values.length != oldValues.length) {
            options.value = values;
            if (options.multiple) {
                options.onChange.call(target, values, oldValues);
            } else {
                options.onChange.call(target, values[0], oldValues[0]);
            }
        }
    };

    var _getValue = function (target) {
        var values = _getValues(target);
        return values[0];
    };
    var _setValue = function (target, comboValue) {
        _setValues(target, [comboValue]);
    };
    var _setInitValues = function (target) {
        var options = $.data(target[0], _cacheName).options;
        var fn = options.onChange;
        options.onChange = function () {
        };
        if (options.multiple) {
            if (options.value) {
                if (typeof options.value == "object") {
                    _setValues(target, options.value);
                    options.originalValue = options.value;
                } else {
                    _setValue(target, options.value);
                    options.originalValue = _getValues(target);
                }
            } else {
                _setValues(target, []);
                options.originalValue = [];
            }
        } else {
            _setValue(target, options.value);
            options.originalValue = options.value;
        }
        options.onChange = fn;
    };
})(jQuery);